/*
 * This file is part of algowala.
 *
 * algowala is copyright (c) 2012 Jagannathan Sampath <algowala@jagernot.com>
 *
 * algowala is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * algowala is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with algowala.  If not, see <http://www.gnu.org/licenses/>.
 *
*/
#ifndef __viewwin
#define __viewwin

#include "box.h"

struct viewport { // opengl viewport

  int width, height;
  int xmax, ymax;
  double xmax_1, ymax_1; // 1.0 / xmax , 1.0 / ymax
  
  // for constant size handle of vertex/tangent in curve editors
  //
  static int handle_radius;
  static float handle_factor;
  
  viewport (int w, int h) {operator() (w, h);}
  void operator() (int width, int height);
  void calc (int w, int h);
  bool inside (int x, int y);

};

struct window : box<double> { // curve editor

  double mousex, mousey; // mouse in window co-ords
  int prev_mousex, prev_mousey; // prev mouse in mouse co-ords

  void locate_mouse (); // find mouse in window co-ords
  void update_mouse (); // update mouse in window co-ords

  double vwx, vwy; // for view-win transform; to locate mouse in window
  void calc_viewwin ();

  static int PAN_RATE, ZOOM_RATE; // num pan, zooms per second
  static double PAN_AMOUNT, ZOOM_AMOUNT; // pan, zoom amount per key press
  static double PAN_REPEAT, ZOOM_REPEAT; // key repeat time
  static void calc_repeats ();

  double pan_x, pan_y;
  void calc_panxy ();
  void panx (int dir);
  void pany (int dir);

  double aspect_ratio;
  double width_1, height_1; // 1.0 / width, 1.0 / height

  float handle_radius, handle_radius2;
  void calc_handle_radius ();


  window ();
  window (double l, double b, double r, double t);
  void set (double l, double b, double r, double t);
  void get (double& l, double& b, double& r, double& t);

  void zoom (int dir);

  void project ();

  inline void calc () {
    calc_repeats ();
    calc_panxy ();
    calc_viewwin ();
    calc_handle_radius ();
    locate_mouse ();
  }


};

inline void view2win (int vx, int vy, double& wx, double& wy, viewport& view, window& win) {

  double xr = vx * view.xmax_1;
  double yr = 1 - vy * view.ymax_1;

  wx = win.left + xr * win.width;
  wy = win.bottom + yr * win.height;

}

inline void win2view (double wx, double wy, int& vx, int& vy, window& win, viewport& view) {

  double xr = (wx - win.left) * win.width_1;
  double yr = (wy - win.bottom) * win.height_1;
  vx = (int) (xr * view.xmax + 0.5);
  vy = (int) (yr * view.ymax + 0.5);

}

#endif
